package com.one.common.model.http;


import com.one.common.model.http.base.BaseResponse;
import com.one.common.model.http.base.CommonResponse;
import com.one.common.model.http.exception.ApiException;
import com.one.common.model.http.proxy.ProxyHandler;
import com.one.common.utils.Logger;
import com.one.common.view.base.MyRxActivity;
import com.one.common.view.base.MyRxFragment;
import com.trello.rxlifecycle2.android.ActivityEvent;
import com.trello.rxlifecycle2.android.FragmentEvent;

import java.lang.reflect.Proxy;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.ObservableTransformer;
import io.reactivex.functions.Function;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by jiejing on 2017/7/24.
 */

public class RetrofitUtil {
    public static final int DEFAULT_TIMEOUT = 60;        //超时时间15s
    public static final int DEFAULT_WRITEREAD_TIMEOUT = 50;//主要是给读取时间使用 ，增加ok的默认读取时间，因为涉及ocr读取缓慢
    private Retrofit mRetrofit;
    private static RetrofitUtil mInstance;

    /**
     * 私有构造方法
     */
    private RetrofitUtil() {
        mRetrofit = getRetrofit(NetConstant.APP_HOST_PRODUCT);
    }

    /**
     * 获取Retrofit对象
     *
     * @param host 域名，接口
     * @return 返回 Retrofit
     */
    private Retrofit getRetrofit(String host) {
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();// 网络log拦截器
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);

        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        builder.writeTimeout(DEFAULT_WRITEREAD_TIMEOUT, TimeUnit.SECONDS);
        builder.readTimeout(DEFAULT_WRITEREAD_TIMEOUT, TimeUnit.SECONDS);
        builder.addInterceptor(logging);

//        builder.addNetworkInterceptor(new Interceptor() {
//            @NotNull
//            @Override
//            public Response intercept(@NotNull Chain chain) throws IOException {
//                Request request = chain.request().newBuilder()
//                        .addHeader("Connection","close").build();
//                return chain.proceed(request);
//            }
//        });


        return new Retrofit.Builder()
                .client(builder.build())
                .baseUrl(host)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
    }

    public static RetrofitUtil getInstance() {
        if (mInstance == null) {
            synchronized (RetrofitUtil.class) {
                mInstance = new RetrofitUtil();
            }
        }
        return mInstance;
    }

    public Retrofit getRetrofit() {
        return mRetrofit;
    }

    /**
     * 这里可以动态设置host
     * @param tClass api接口类
     * @param host host
     * @param <T> 泛型
     * @return api控制类
     */
    @SuppressWarnings("unchecked")
    public <T> T getProxy(Class<T> tClass, String host) {
        T t;
        if (host.equals(NetConstant.APP_HOST)) {
            t = mRetrofit.create(tClass);
        } else {
            t = getRetrofit(host).create(tClass);
        }
        return (T) Proxy.newProxyInstance(tClass.getClassLoader(), new Class<?>[]{tClass}, new ProxyHandler(t));
    }

    public <T> T getProxy(Class<T> tClass) {
        return getProxy(tClass, NetConstant.APP_HOST_PRODUCT);
    }

    /**
     * 统一返回结果处理
     */
    public static <T extends BaseResponse> ObservableTransformer<CommonResponse<T>, T> handleResult() {   //compose判断结果
        return upstream -> upstream.map((Function<CommonResponse<T>, T>) tBaseResponse -> {
            Logger.d("okhttp ");
            Logger.d("retrofit  得到结果");
            if (tBaseResponse == null) {
                throw new ApiException("error", "服务器异常");
            } else if (!tBaseResponse.getResult_code().equals("200") || tBaseResponse.getResult() == null) {
                throw new ApiException(tBaseResponse.getResult_code(), tBaseResponse.getResult_msg());
            } else if(tBaseResponse.getResult() != null){
                // 请求成功咯
            }
            return tBaseResponse.getResult();

        });
    }

    public static <T> ObservableTransformer<T, T> handleResultT() {   //compose判断结果
        return upstream -> upstream.map((Function<T, T>) tBaseResponse -> tBaseResponse);
    }

    public <T> Observable<T> getObservableT(Observable<T> observable, MyRxActivity activity) {
        return observable
                .compose(activity.<T>bindUntilEvent(ActivityEvent.DESTROY))
                .compose(RxHelper.<T>rxSchedulerHelper())//切换线程
                .compose(RetrofitUtil.<T>handleResultT());    //从BaseResponse中得到具体的实例
    }
    public <T> Observable<T> getObservableT(Observable<T> observable) {
        return observable
                .compose(RxHelper.<T>rxSchedulerHelper())//切换线程
                .compose(RetrofitUtil.<T>handleResultT());    //从BaseResponse中得到具体的实例
    }
    /**
     * 抽离请求中对观察者的处理
     *
     * @param observable 需要处理的观察者
     * @param activity   所在页面
     * @param <T>        类型
     * @return 处理后的观察者
     */
    public <T extends BaseResponse> Observable<T> getObservable(Observable<CommonResponse<T>> observable, MyRxActivity activity) {
        Logger.d("retrofit  注册观察者");
        return observable
                .compose(activity.<CommonResponse<T>>bindUntilEvent(ActivityEvent.DESTROY))
                .compose(RxHelper.<CommonResponse<T>>rxSchedulerHelper())//切换线程
                .compose(RetrofitUtil.<T>handleResult());    //从BaseResponse中得到具体的实例
    }

    /**
     * 抽离请求中对观察者的处理
     * 不绑定activity 生命周期
     *
     * @param observable 需要处理的观察者
     * @param <T>        类型
     * @return 处理后的观察者
     */
    public <T extends BaseResponse> Observable<T> getObservable(Observable<CommonResponse<T>> observable) {
        return observable
                .compose(RxHelper.<CommonResponse<T>>rxSchedulerHelper())//切换线程
                .compose(RetrofitUtil.<T>handleResult());    //从BaseResponse中得到具体的实例
    }

    /**
     * 抽离请求中对观察者的处理
     *
     * @param observable 需要处理的观察者
     * @param fragment   所在页面
     * @param <T>        类型
     * @return 处理后的观察者
     */
    public <T extends BaseResponse> Observable<T> getObservable(Observable<CommonResponse<T>> observable, MyRxFragment fragment) {
        return observable
                .compose(fragment.<CommonResponse<T>>bindUntilEvent(FragmentEvent.PAUSE))
                .compose(RxHelper.<CommonResponse<T>>rxSchedulerHelper())//切换线程
                .compose(RetrofitUtil.<T>handleResult());    //从BaseResponse中得到具体的实例
    }


}